#include "tcpmgr.h"
#include "usermgr.h"
#include <QAbstractSocket>
TcpMgr::~TcpMgr()
{

}

TcpMgr::TcpMgr():_host(""),_port(0),_is_pending(false),_head_id(0),_head_len(0)
{
    //连接后触发
    QObject::connect(&_socket,&QTcpSocket::connected,[&](){
        qDebug()<< "connect:" << _host <<":"<< _port;
        emit sig_con_success(true);
    });

    //有数据可读
    QObject::connect(&_socket,&QTcpSocket::readyRead,[&](){
        // 读取所有数据并追加到缓冲区
        _buffer.append(_socket.readAll());
        QDataStream stream(&_buffer,QIODevice::ReadOnly);
        stream.setVersion(QDataStream::Qt_5_0);
        forever{
            if(!_is_pending){
                if(_buffer.size()< static_cast<int>(sizeof(quint16)*2)){
                    return;
                }
                stream >> _head_id >> _head_len;
                _buffer = _buffer.mid(sizeof(quint16)*2);
                qDebug()<<"msg_id:"<<_head_id << " msg_len:"<<_head_len;
            }
            if(_buffer.size()<_head_len){
                _is_pending = true;
                return;
            }

            QByteArray msg_data = _buffer.mid(0,_head_len);
            qDebug()<<"msg_data:"<< msg_data;
            _is_pending = false;
            _buffer = _buffer.mid(_head_len);
            handleMsg(ReqId(_head_id),_head_len,msg_data);
        }
    });

    //连接出错处理
    QObject::connect(&_socket, static_cast<void (QTcpSocket::*)(QTcpSocket::SocketError)>(&QTcpSocket::error),
                        [&](QTcpSocket::SocketError socketError) {
           qDebug() << "Error:" << _socket.errorString() ;
           switch (socketError) {
               case QTcpSocket::ConnectionRefusedError:
                   qDebug() << "Connection Refused!";
                   emit sig_con_success(false);
                   break;
               case QTcpSocket::RemoteHostClosedError:
                   qDebug() << "Remote Host Closed Connection!";
                   break;
               case QTcpSocket::HostNotFoundError:
                   qDebug() << "Host Not Found!";
                   emit sig_con_success(false);
                   break;
               case QTcpSocket::SocketTimeoutError:
                   qDebug() << "Connection Timeout!";
                   emit sig_con_success(false);
                   break;
               case QTcpSocket::NetworkError:
                   qDebug() << "Network Error!";
                   break;
               default:
                   qDebug() << "Other Error!";
                   break;
           }
     });

    QObject::connect(&_socket,&QTcpSocket::disconnected,[](){
        qDebug()<<"disconnected";
    });

    QObject::connect(this,&TcpMgr::sig_send_data,this,&TcpMgr::slot_send_data);
    initHandles();
}

void TcpMgr::initHandles()
{
    _handles.insert(ID_CHAT_LOGIN_RSP, [this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "Login Failed, err is Json Parse Err" << err ;
            emit sig_login_fail(err);
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "Login Failed, err is " << err ;
            emit sig_login_fail(err);
            return;
        }
        qDebug() << "彻彻底底的登录了";
        auto uid = jsonObj["uid"].toInt();
        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto user_info = std::make_shared<UserInfo>(uid, name, nick, icon, sex);

        UserMgr::GetInstance()->SetUserInfo(user_info);
        UserMgr::GetInstance()->SetToken(jsonObj["token"].toString());
        if(jsonObj.contains("apply_list")){
            UserMgr::GetInstance()->AppendApplyList(jsonObj["apply_list"].toArray());
        }

        if(jsonObj.contains("friend_list")){
            UserMgr::GetInstance()->AppendFriendList(jsonObj["friend_list"].toArray());
        }

        qDebug()<<"------------" << UserMgr::GetInstance()->GetName();
        emit sig_switch_chatdlg();
    });

    _handles.insert(ReqId::ID_SEARCH_USER_RSP,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "search Failed, err is Json Parse Err" << err ;
            emit sig_user_search_fail(err);
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "search Failed, err is " << err ;
            emit sig_user_search_fail(err);
            return;
        }
        auto search_info = std::make_shared<SearchInfo>(jsonObj["uid"].toInt(),
                jsonObj["name"].toString(), jsonObj["nick"].toString(),
                jsonObj["desc"].toString(), jsonObj["sex"].toInt(), jsonObj["icon"].toString());
         emit sig_user_search(search_info);
    });

    _handles.insert(ReqId::ID_ADD_FRIEND_RSP,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "add_friend_rsp Failed, err is Json Parse Err" << err ;
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "add_friend_rsp Failed, err is " << err ;
            return;
        }
        qDebug() << "Add Friend Request Success .";
    });
    //服务器通知客户端添加好友
    _handles.insert(ReqId::ID_NOTIFY_ADD_FRIEND_REQ,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "NOTIFY_ADD_FRIEND Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "NOTIFY_ADD_FRIEND Failed, err is Json Parse Err" << err ;
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "NOTIFY_ADD_FRIEND Failed, err is " << err ;
            return;
        }
        //通知添加好友
        int from_uid = jsonObj["applyuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString desc = jsonObj["desc"].toString();
        QString icon = jsonObj["icon"].toString();
        QString nick = jsonObj["nick"].toString();
        int sex = jsonObj["sex"].toInt();
       auto apply_info = std::make_shared<AddFriendApply>(
                   from_uid, name, desc,
                     icon, nick, sex);
       emit sig_friend_apply(apply_info);
       qDebug() << "notify add friend success";
    });

    _handles.insert(ReqId::ID_AUTH_FRIEND_RSP,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "AUTH_FRIEND_RSP Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "AUTH_FRIEND_RSP Failed, err is Json Parse Err" << err ;
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "AUTH_FRIEND_RSP Failed, err is " << err ;
            return;
        }

        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto uid = jsonObj["uid"].toInt();
        auto rsp = std::make_shared<AuthRsp>(uid, name, nick, icon, sex);
        emit sig_auth_rsp(rsp);

        qDebug() << "Auth Friend Success " ;

    });

    _handles.insert(ReqId::ID_NOTIFY_AUTH_FRIEND_REQ,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "NOTIFY_AUTH_FRIEND_REQ Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "NOTIFY_AUTH_FRIEND_REQ Failed, err is Json Parse Err" << err ;
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "NOTIFY_AUTH_FRIEND_REQ Failed, err is " << err ;
            return;
        }

        auto name = jsonObj["name"].toString();
        auto nick = jsonObj["nick"].toString();
        auto icon = jsonObj["icon"].toString();
        auto sex = jsonObj["sex"].toInt();
        auto uid = jsonObj["fromuid"].toInt();
        auto rsp = std::make_shared<AuthInfo>(uid, name, nick, icon, sex);
        emit sig_add_auth_friend(rsp);

        qDebug() << "NOTIFY AUTH FRIEND Friend Success " ;

    });
    //1018,1019
    _handles.insert(ReqId::ID_TEXT_CHAT_MSG_RSP,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "TEXT_CHAT_MSG_RSP Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "TEXT_CHAT_MSG_RSP Failed, err is Json Parse Err" << err ;
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "TEXT_CHAT_MSG_RSP Failed, err is " << err ;
            return;
        }

        qDebug() << "Send msg success";
    });

    _handles.insert(ReqId::ID_NOTIFY_TEXT_CHAT_MSG_REQ,[this](ReqId id, int len, QByteArray data){
        Q_UNUSED(len);
        qDebug()<< "handle id is "<< id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转换是否成功
        if(jsonDoc.isNull()){
           qDebug() << "NOTIFY_TEXT_CHAT_MSG_REQ Failed to create QJsonDocument.";
           return;
        }

        QJsonObject jsonObj = jsonDoc.object();

        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "NOTIFY_TEXT_CHAT_MSG_REQ Failed, err is Json Parse Err" << err ;
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "NOTIFY_TEXT_CHAT_MSG_REQ Failed, err is " << err ;
            return;
        }

        auto msg_ptr = std::make_shared<TextChatMsg>(jsonObj["fromuid"].toInt(),
                jsonObj["touid"].toInt(),jsonObj["text_array"].toArray());
        emit sig_text_chat_msg(msg_ptr);

        qDebug() << "nodify recv msg success";
    });

}

void TcpMgr::handleMsg(ReqId id, int len, QByteArray &data)
{
    auto find_iter =  _handles.find(id);
    qDebug()<<"client recv: id" <<id;
    if(find_iter == _handles.end()){
         qDebug()<< "not found id ["<< id << "] to handle";
         return ;
    }
    find_iter.value()(id,len,data);
}

void TcpMgr::slot_tcp_connect(ServerInfo si)
{
    qDebug()<<"client connecting to chatserver.token:" <<si.Token;
    _host = si.Host;
    _port = static_cast<uint16_t>(si.Port.toInt());
    _socket.connectToHost(si.Host,static_cast<uint16_t>(si.Port.toInt()));
}

void TcpMgr::slot_send_data(ReqId reqId, QByteArray data)
{
    uint16_t id = reqId;
    qDebug()<<"send to chatserver reqid:" << reqId <<" reqdata:"<<data;

    // 计算长度（使用网络字节序转换）
    quint16 len = static_cast<quint16>(data.size());

    // 创建一个QByteArray用于存储要发送的所有数据
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);

    // 设置数据流使用网络字节序
    out.setByteOrder(QDataStream::BigEndian);

    // 写入ID和长度
    out << id << len;

    // 添加字符串数据
    block.append(data);
    // 发送数据
    _socket.write(block);
}




